package com.peas.platform.common.core.configuration;

import cn.hutool.core.util.StrUtil;
import com.peas.platform.common.core.constant.Constants;
import com.peas.platform.common.core.exception.BaseException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * @author caizhh
 */
@Slf4j
public class RequestContextUtil {

    private static final ThreadLocal<Map<RequestContextUtilEnum, String>> contextHolder = new InheritableThreadLocal<>();

    @SneakyThrows
    private RequestContextUtil() {
        throw new NoSuchMethodException();
    }

    public synchronized static Map<RequestContextUtilEnum, String> getCurrentContext() {
        Map<RequestContextUtilEnum, String> context = contextHolder.get();
        if (context == null) {
            log.debug("getCurrentContext():RequestContext is null, new RequestContext() in Thread " + Thread.currentThread().getName());
            Map<RequestContextUtilEnum, String> requestContext = new HashMap<>();
            reset(requestContext);
            contextHolder.set(requestContext);
            context = contextHolder.get();
        }
        return context;
    }

    public static void close(Map<RequestContextUtilEnum, String> requestContext) {
        reset(requestContext);
        log.debug("RequestContext close");
        contextHolder.remove();
    }

    private static void reset(Map<RequestContextUtilEnum, String> requestContext) {
        log.debug("RequestContext reset:" + requestContext.get(RequestContextUtilEnum.requestId) + "," + requestContext.get(RequestContextUtilEnum.sso_sessionid));
        requestContext.put(RequestContextUtilEnum.application, null);
        requestContext.put(RequestContextUtilEnum.requestId, null);
        requestContext.put(RequestContextUtilEnum.sso_sessionid, null);
        requestContext.put(RequestContextUtilEnum.userId, null);
        requestContext.put(RequestContextUtilEnum.userCode, null);
        requestContext.put(RequestContextUtilEnum.account, null);
        requestContext.put(RequestContextUtilEnum.resourceCode, null);
        requestContext.put(RequestContextUtilEnum.init_timestamp_millis, null);
    }

    public static RequestContext getRequestContext() {
        RequestContext rc = new RequestContext();
        rc.setTraceId(RequestContextUtil.getCurrentRequestId());
        rc.setUserId(RequestContextUtil.getCurrentUserId());
        rc.setUserCode(RequestContextUtil.getCurrentUserCode());
        rc.setSsoSessionId(RequestContextUtil.getCurrentSsoSessionId());
        rc.setAccount(RequestContextUtil.getCurrentAccount());
        rc.setResourceCode(RequestContextUtil.getResourceCode());
        return rc;
    }

    public static String getCurrentSsoSessionId() {
        return getCurrentSsoSessionId(false);
    }

    public static String getCurrentSsoSessionId(boolean threw) {
        String ssoSessionId = getCurrentContext().get(RequestContextUtilEnum.sso_sessionid);
        if (threw && StrUtil.isBlank(ssoSessionId)) {
            throw new BaseException(Constants.LOGIN_ERROR_CODE, Constants.LOGIN_ERROR_MESSAGE);
        }
        return ssoSessionId;
    }

    public static String getCurrentUserId() {
        return getCurrentUserId(false);
    }

    public static String getCurrentUserId(boolean threw) {
        String user = getCurrentContext().get(RequestContextUtilEnum.userId);
        if (threw && StrUtil.isBlank(user)) {
            throw new BaseException(Constants.LOGIN_ERROR_CODE, Constants.LOGIN_ERROR_MESSAGE);
        }
        return user;
    }

    public static String getCurrentUserCode() {
        return getCurrentContext().get(RequestContextUtilEnum.userCode);
    }

    public static String getCurrentAccount() {
        return getCurrentContext().get(RequestContextUtilEnum.account);
    }

    public static String getCurrentRequestId() {
        return getCurrentContext().get(RequestContextUtilEnum.requestId);
    }

    public static String getResourceCode() {
        return getCurrentContext().get(RequestContextUtilEnum.resourceCode);
    }

    public static Long getInitTimestampMillis() {
        String millis = getCurrentContext().get(RequestContextUtilEnum.init_timestamp_millis);
        if (millis != null) {
            return Long.valueOf(millis);
        }
        return null;
    }

}
